Skip to content

《C语言程序设计》第一学期重修试卷A (精选01)

一、选择题(本题共20小题,每题2分,共40分)

(1) 在 C 语言中,如果下面的变量都是 int 类型,则输出的结果是 (C)。

c
int sum = 5, pad = 5, pAd;
pAd = sum++;
pAd++;
++pAd;
printf("%d\n", pad);

A) 7 B) 6 C) 5 D) 4

查看答案与解析

答案:C

解析: 本题考查逗号运算符、自增运算符以及变量赋值。

  1. sum = pad = 5;:将 sumpad 都初始化为 5。
  2. pAd = sum++;:后缀自增运算符 ++ 的优先级高于赋值,但它的特性是“先使用后自增”。因此先将 sum 的当前值(5)赋给 pAd,然后 sum 的值变为 6。此时 pAd = 5, sum = 6
  3. pAd++;pAd 自增 1,变为 6。
  4. ++pAd;pAd 自增 1,变为 7。
  5. printf("%d\n", pad);:注意这里打印的是 pad,而不是 pAd。变量 pad 的值从始至终没有被修改,依然是初始值 5。

故输出结果为 5,选 C


难度: ⭐ 考点: #自增运算符 #变量赋值 #逗号运算符

💡 学习锦囊

📖 相关公式与知识点:

  • 前缀自增 ++x:先自增,后参与运算。
  • 后缀自增 x++:先参与运算,后自增。

思路分析

做此类题目时,一定要看清 printf 打印的变量名。本题中 pAd 经历了一系列复杂的运算,但最后打印的却是从未改变的 pad,这是典型的“障眼法”。

易错点

  • 混淆 padpAd,误算出 pAd 的最终值 7 而错选 A。
🔄 举一反三
  1. 若将代码改为 printf("%d\n", sum);,输出结果是什么?
    查看练习答案与解析

    答案:6 解析sum 在执行 pAd = sum++; 时发生了自增,值从 5 变为 6。

(2) 以下程序的输出结果是 (B)。

c
#include <stdio.h>
main()
{
    int i = 010, j = 10;
    printf("%d, %d\n", ++i, j--);
}

A) 11, 10 B) 9, 10 C) 010, 9 D) 10, 9

查看答案与解析

答案:B

解析: 本题考查八进制常量以及自增自减运算符。

  1. int i = 010;:以数字 0 开头的整型常量表示八进制数。八进制的 010 转换为十进制为 $1 \times 8^1 + 0 \times 8^0 = 8$
  2. int j = 10;:十进制的 10。
  3. ++i:前缀自增,i 先变为 9,然后参与打印,输出 9。
  4. j--:后缀自减,先参与打印(输出当前值 10),然后再自减变为 9。

因此输出为 9, 10,选 B


难度: ⭐⭐ 考点: #八进制 #自增自减运算符

💡 学习锦囊

📖 相关公式与知识点:

  • 八进制数以 0 开头,十六进制数以 0x0X 开头。
  • printf("%d") 以十进制形式输出。

思路分析

识别出 010 是八进制数是解题的关键,不要误以为是十进制的 10。

易错点

  • 忽视前导 0,将 010 误认为十进制的 10。
  • 混淆前缀 ++ 和后缀 -- 的执行顺序。
🔄 举一反三
  1. 若定义 int i = 0x10;,则 printf("%d", i); 的输出结果是什么?
    查看练习答案与解析

    答案:16 解析0x10 是十六进制数,转换为十进制为 $1 \times 16^1 + 0 \times 16^0 = 16$

(3) 已知在 ASCII 代码中, 字母 A 的序号为 65 , 以下程序的输出的结果是 (D)。

c
#include <stdio.h>
main()
{
    char c1 = 'A', c2 = 'Y';
    printf("%d, %d\n", c1, c2);
}

A) 因输出格式不合法, 输出错误信息 B) 65, 90 C) A, Y D) 65, 89

查看答案与解析

答案:D

解析: 本题考查字符型数据与整型数据的转换以及 ASCII 码。

  1. c1 = 'A',其 ASCII 码值为 65。
  2. c2 = 'Y','Y' 与 'A' 相差 24 个字母('Y' - 'A' = 24),所以 'Y' 的 ASCII 码值为 $65 + 24 = 89$
  3. printf("%d, %d\n", c1, c2);:使用 %d 格式符打印字符变量,会将字符对应的 ASCII 码值以整数形式输出。

因此输出为 65, 89,选 D


难度: ⭐ 考点: #ASCII码 #printf格式符

💡 学习锦囊

📖 相关公式与知识点:

  • 常见 ASCII 码:'A' 为 65,'a' 为 97,'0' 为 48。
  • %d 以整数形式输出,%c 以字符形式输出。

思路分析

字符在内存中是以 ASCII 码的二进制形式存储的,可以直接当作整数参与运算或按整数输出。

易错点

  • 误以为打印字符必须用 %c,看到 %d 以为格式不合法。
  • 计算 'Y' 的 ASCII 码时数错字母顺序。
🔄 举一反三
  1. printf("%c, %c\n", c1, c2);,输出结果是什么?
    查看练习答案与解析

    答案:A, Y 解析:使用 %c 格式符会按字符形式输出。

(4) 语句 while(!E);中的条件!E 等价于 (A)。

A) E == 0 B) E != 1 C) E != 0 D) ~E

查看答案与解析

答案:A

解析: 本题考查逻辑非运算符与条件判断。

  1. 在 C 语言中,逻辑真用非零表示,逻辑假用 0 表示。
  2. 逻辑非运算符 ! 会将真变为假,假变为真。
  3. 因此,当 E 为 0(假)时,!E 为真(非零);当 E 为非零(真)时,!E 为假(0)。
  4. 这与表达式 E == 0 的逻辑一致:当 E 等于 0 时,表达式成立(真);当 E 不等于 0 时,表达式不成立(假)。

!E 等价于 E == 0,选 A


难度: ⭐ 考点: #逻辑运算符 #条件判断

💡 学习锦囊

📖 相关公式与知识点:

  • !x 等价于 x == 0
  • x(作为条件)等价于 x != 0

思路分析

理解 C 语言中“非零即真,零为假”的原则是解题的关键。

易错点

  • 混淆按位取反 ~ 和逻辑非 !
  • 误认为 !E 等价于 E != 0
🔄 举一反三
  1. 语句 if(E) 中的条件 E 等价于什么?
    查看练习答案与解析

    答案:E != 0 解析:只要 E 不为 0,条件即为真。

(5) 以下程序的输出结果是 (B)。

c
#include <stdio.h>
main()
{
    printf("%d\n", NULL);
}

A) 不确定的(因变量无定义) B) 0 C) -1 D) 1

查看答案与解析

答案:B

解析: 本题考查宏定义 NULL 的含义。

  1. NULL 是 C 语言标准库中定义的一个宏,通常表示空指针。
  2. 在大多数编译器中,NULL 被定义为 0((void *)0)
  3. 当使用 %d 打印 NULL 时,它会被作为整数 0 输出。

故输出结果为 0,选 B


难度: ⭐ 考点: #NULL指针 #宏定义

💡 学习锦囊

📖 相关公式与知识点:

  • NULL 通常在 <stdio.h><stddef.h> 中定义。

思路分析

记住 NULL 在本质上等同于数值 0 即可。

易错点

  • 误认为 NULL 是未定义的变量导致编译错误。
🔄 举一反三
  1. sizeof(NULL) 在 64 位系统下通常是多少字节?
    查看练习答案与解析

    答案:8 解析NULL 本质是指针,64 位系统下指针占用 8 字节。

(6) 以下函数调用语句中含有 (B) 个实参。

c
func((exp1, exp2), (exp3, exp4, exp5));

A) 1 B) 2 C) 4 D) 5

查看答案与解析

答案:B

解析: 本题考查逗号运算符与函数调用实参。

  1. 函数调用时,实参之间用逗号分隔。
  2. func((exp1, exp2), (exp3, exp4, exp5)) 中,最外层的逗号将参数分隔为两部分:
    • 第一部分:(exp1, exp2)
    • 第二部分:(exp3, exp4, exp5)
  3. 每一部分都是一个由括号包裹的表达式。在 C 语言中,括号内的逗号是逗号运算符
  4. 逗号运算符的规则是:从左到右依次计算各个表达式,整个表达式的值是最后一个表达式的值。
  5. 因此,(exp1, exp2) 作为一个整体传递给函数,是 1 个实参;(exp3, exp4, exp5) 也作为一个整体传递,是 1 个实参。

故实参个数为 2,选 B


难度: ⭐⭐ 考点: #逗号运算符 #函数实参

💡 学习锦囊

📖 相关公式与知识点:

  • 函数调用语法:函数名(实参1, 实参2, ...)
  • 逗号表达式:(表达式1, 表达式2, ..., 表达式n),其值为 表达式n 的值。

思路分析

区分“作为参数分隔符的逗号”和“作为运算符的逗号”。被括号包裹的逗号属于逗号运算符,不增加参数个数。

易错点

  • 简单地数逗号个数,误以为有 4 个或 5 个参数。
🔄 举一反三
  1. func(exp1, exp2, exp3, exp4); 含有几个实参?
    查看练习答案与解析

    答案:4 解析:没有括号包裹,逗号作为参数分隔符,共 4 个实参。

(7) 下面的程序中 (C) 有错误(每行程序前面的数字是行号)。

c
1 #include <stdio.h>
2 main()
3 {
4     float a[3] = {0.0};
5 int i;
6 for(i = 0; i < 3; i++) s;
7 for(i = 1; i < 3; i++) a;
8 printf("%f\n", a[0]);
9 }

A) 没有 B) 第4行 C) 第6行 D) 第8行

查看答案与解析

答案:C

解析: 本题考查语法错误分析。

  1. 第 4 行:float a[3] = {0.0}; 正确,初始化数组元素为 0。
  2. 第 6 行:for(i = 0; i < 3; i++) s; 错误。变量 s 未定义,直接使用会导致编译错误(Undefined symbol 's')。
  3. 第 7 行:for(i = 1; i < 3; i++) a; 虽然无实际意义,但 a 是已定义的数组名(地址常量),在语法上是合法的表达式语句。
  4. 第 8 行:printf("%f\n", a[0]); 正确。

故第 6 行有错误,选 C


难度: ⭐⭐ 考点: #语法错误 #变量未定义

💡 学习锦囊

📖 相关公式与知识点:

  • 任何变量在被使用前必须先进行定义。
  • 数组名在表达式中会被转换为指向数组首元素的指针。

思路分析

逐行检查语法,重点关注未定义的变量和拼写错误。

易错点

  • 忽视变量 s 的未定义状态。
  • 误认为第 7 行的 a; 是语法错误。
🔄 举一反三
  1. 若在第 5 行增加 int s = 0;,程序是否还有错误?
    查看练习答案与解析

    答案:没有 解析:定义了 s 之后,第 6 行的 s; 变为合法语句。

(8) 设有语句 int $a = 3$; 则执行了语句 $a += a -= a * a$; 后, 变量 $a$ 的值是 (D)。

A) 3 B) 0 C) 9 D) -12

查看答案与解析

答案:D

解析: 本题考查复合赋值运算符的右结合性。

  1. 初始状态 a = 3
  2. 表达式为 a += a -= a * a。赋值运算符具有右结合性,即从右向左依次计算。
  3. 首先计算右侧的 a -= a * a
    • a * a 的值为 $3 \times 3 = 9$
    • a -= 9 等价于 a = a - 9,此时 a 变为 $3 - 9 = -6$
  4. 接着计算左侧的 a += (-6)
    • 此时 a 的值已经变为 -6。
    • a += -6 等价于 a = a + (-6),即 $a = -6 + (-6) = -12$

故最终 a 的值为 -12,选 D


难度: ⭐⭐ 考点: #复合赋值运算符 #运算符结合性

💡 学习锦囊

📖 相关公式与知识点:

  • 赋值运算符(=, +=, -=, *= 等)的优先级较低,且结合性为从右到左

思路分析

关键在于“右结合性”和“变量值的实时更新”。计算出右侧结果后,左侧运算使用的 a 已经是更新后的值了。

易错点

  • 忽略右结合性,从左往右算。
  • 在算左侧 a += 时,错误地使用了 a 的初始值 3。
🔄 举一反三
  1. int a = 2;,执行 a += a *= a; 后,a 的值是多少?
    查看练习答案与解析

    答案:8 解析:先算 a *= aa = 4。再算 a += 4a = 4 + 4 = 8

(9) 以下的 for 循环 (C)。

c
for(x = 0, y = 0; (y != 123) && (x < 4); x++);

A) 是无限循环 B) 循环次数不定 C) 执行 4 次 D) 执行 3 次

查看答案与解析

答案:C

解析: 本题考查 for 循环的执行次数判定。

  1. 循环初始化:x = 0, y = 0
  2. 循环条件:(y != 123) && (x < 4)
  3. 循环迭代:x++
  4. 循环体:为空语句(分号 ; 紧跟在括号后)。
  5. 过程分析:
    • 第一次:x=0, y=0。条件 (0 != 123) && (0 < 4) 为真。执行空语句,x 变为 1。
    • 第二次:x=1, y=0。条件 (0 != 123) && (1 < 4) 为真。执行空语句,x 变为 2。
    • 第三次:x=2, y=0。条件 (0 != 123) && (2 < 4) 为真。执行空语句,x 变为 3。
    • 第四次:x=3, y=0。条件 (0 != 123) && (3 < 4) 为真。执行空语句,x 变为 4。
    • 第五次:x=4, y=0。条件 (0 != 123) && (4 < 4) 为假。循环结束。

循环体共被执行了 4 次,选 C


难度: ⭐ 考点: #for循环 #循环条件

💡 学习锦囊

📖 相关公式与知识点:

  • for(初始化; 条件; 迭代),只要条件为假,循环立即终止。
  • 空语句 ; 也是合法的语句。

思路分析

注意 y 在循环过程中没有改变,一直是 0。因此循环的终止完全由 x < 4 决定。

易错点

  • 误以为 x 最终值为 3 而错选 D。
  • 误以为 y != 123 会导致无限循环。
🔄 举一反三
  1. 若将条件改为 (y != 123) || (x < 4),循环次数是多少?
    查看练习答案与解析

    答案:无限循环 解析:因为 y 一直是 0,y != 123 永远为真,逻辑或 || 导致整体条件永远为真。

(10) 设有语句 char a = '\72'; 则变量 a (A)。

A) 包含 1 个字符 B) 包含 2 个字符 C) 包含 3 个字符 D) 说明不合法

查看答案与解析

答案:A

解析: 本题考查转义字符的识别。

  1. '\72' 是一个转义字符。
  2. 以反斜杠 \ 开头,后面跟着 1 到 3 位八进制数的字符常量表示转义字符。
  3. \72 表示八进制数 72 对应的字符。
  4. 无论转义字符的形式多么复杂,它在内存中都只占用 1 个字节,表示 1 个字符

故选 A


难度: ⭐ 考点: #转义字符 #char类型

💡 学习锦囊

📖 相关公式与知识点:

  • 八进制转义字符:\ddd(1-3位八进制数)。
  • 十六进制转义字符:\xhh(1-2位十六进制数)。

思路分析

转义字符虽然书写上有多个字符,但本质上代表的是一个单一的 ASCII 字符。

易错点

  • \72 当成 3 个独立的字符。
🔄 举一反三
  1. 语句 char a = '\x41'; 中变量 a 包含几个字符?
    查看练习答案与解析

    答案:1 个 解析\x41 是十六进制转义字符,代表字符 'A',占 1 个字符。

(11) C 语言中 (D)。

A) 不能使用 do-while 语句构成的循环 B) do-while 语句构成的循环必须用 break 语句才能退出 C) do-while 语句构成的循环,当 while 语句中的表达式值为非零时结束循环 D) do-while 语句构成的循环,当 while 语句中的表达式值为零时结束循环

查看答案与解析

答案:D

解析: 本题考查 do-while 循环的执行机制。

  1. do-while 循环的语法结构为:do { 循环体 } while (表达式);
  2. 它的特点是“先执行,后判断”。无论条件如何,循环体至少会被执行一次。
  3. 循环的继续与结束取决于 while 后面的表达式:当表达式的值为**真(非零)时,继续循环;当表达式的值为假(零)**时,结束循环。

故选 D


难度: ⭐ 考点: #do-while循环 #循环控制

💡 学习锦囊

📖 相关公式与知识点:

  • while 循环:先判断,后执行。
  • do-while 循环:先执行,后判断(至少执行一次)。

思路分析

牢记 C 语言中条件判断的本质:非零为真继续,零为假退出。

易错点

  • 误以为 do-while 循环在条件为假时才继续。
🔄 举一反三
  1. 下面代码的输出结果是什么?
    c
    int i = 5;
    do {
        printf("%d", i);
    } while(0);
    查看练习答案与解析

    答案:5 解析:条件为 0(假),但 do-while 先执行一次,打印 5 后退出。

(12) 以下程序的输出结果是 (A)。

c
#include <stdio.h>
#include <string.h>
main()
{
    char str[12] = {'s', 't', 'r', 'i', 'n', 'g'};
    printf("%d\n", strlen(str));
}

A) 6 B) 7 C) 11 D) 12

查看答案与解析

答案:A

解析: 本题考查数组初始化与 strlen 函数。

  1. char str[12] = {'s', 't', 'r', 'i', 'n', 'g'};:定义了一个长度为 12 的字符数组。显式初始化了前 6 个元素。
  2. 根据 C 语言规则,部分初始化的数组,未显式初始化的元素会被自动赋值为该类型的零值。对于字符数组,零值即为空字符 \0
  3. strlen(str) 函数用于计算字符串的长度,其机制是从字符串首地址开始计数,直到遇到第一个空字符 \0 为止(不包含 \0)。
  4. 数组内容为 's', 't', 'r', 'i', 'n', 'g', '\0', ...strlen 计数的字符个数为 6。

故输出结果为 6,选 A


难度: ⭐⭐ 考点: #strlen函数 #数组初始化

💡 学习锦囊

📖 相关公式与知识点:

  • strlen 返回的是有效字符个数。
  • sizeof 返回的是整个数组占用的内存字节数。

思路分析

明确 strlensizeof 的区别。本题中 sizeof(str) 为 12,而 strlen(str) 为 6。

易错点

  • 混淆 strlensizeof
🔄 举一反三
  1. 若将代码改为 printf("%d", sizeof(str));,输出结果是什么?
    查看练习答案与解析

    答案:12 解析sizeof 计算整个数组的内存大小,长度为 12。

(13) 以下程序的输出结果是 (A)。

c
#include <stdio.h>
main()
{
    int a = 2, c = 5;
    printf("a=%%%d,b=%%%d\n", a, c);
}

A) a=%2,b=%5 B) a=2,b=5 C) a=%%d,b=%%d D) a=%d,b=%d

查看答案与解析

答案:A

解析: 本题考查 printf 中百分号 % 的转义输出。

  1. printf 的格式控制字符串中,% 是格式说明符的起始标志。
  2. 如果想要在屏幕上打印出一个 % 字符,需要使用两个连续的百分号 %% 来表示转义。
  3. 在字符串 "a=%%%d,b=%%%d\n" 中:
    • 前两个 % 组合成 %%,输出一个 %
    • 第三个 % 与后面的 d 组合成 %d,输出对应变量的值(a 的值 2)。
    • 组合起来就是 a=%2。同理,后半部分输出 b=%5

故输出为 a=%2,b=%5,选 A


难度: ⭐⭐ 考点: #printf格式化输出 #百分号转义

💡 学习锦囊

📖 相关公式与知识点:

  • printf 中,%% 用于输出一个 %

思路分析

理清格式控制字符串中 % 的两两配对关系。

易错点

  • 误以为 %%d 会直接打印出 %d 文本。
🔄 举一反三
  1. printf("%%d"); 的输出结果是什么?
    查看练习答案与解析

    答案:%d 解析%% 转义为 %,后面跟着普通字符 d

(14) 以下程序的输出结果是 (B)。

c
#include <stdio.h>
main()
{
    int a, b, d = 241;
    a = d / 100 % 9;
    b = (-1) && (-1);
    printf("%d,%d\n", a, b);
}

A) 6,1 B) 2,1 C) 6,0 D) 2,0

查看答案与解析

答案:B

解析: 本题考查算术运算与逻辑运算。

  1. d / 100:整型除法,$241 / 100 = 2$
  2. 2 % 9:求余运算,商 0 余 2,所以 a = 2
  3. b = (-1) && (-1):逻辑与运算。在 C 语言中,非零值即为真。-1 为真,真 && 真 的结果为真(1)。所以 b = 1
  4. printf 打印出 2,1

故选 B


难度: ⭐ 考点: #整型除法 #求余运算 #逻辑与

💡 学习锦囊

📖 相关公式与知识点:

  • 整数相除只保留整数部分。
  • 逻辑运算的结果只有 0(假)和 1(真)。

思路分析

注意 C 语言中负数(如 -1)在逻辑判断中也是“真”。

易错点

  • 误以为 -1 是假。
🔄 举一反三
  1. b = (-1) || (0);b 的值是多少?
    查看练习答案与解析

    答案:1 解析-1 为真,逻辑或运算只要有一个为真即为 1。

(15) 以下 for 语句构成的循环执行了 (C) 次。

c
#include <stdio.h>
#define N 2
#define M N+1
#define NUM (M + 1)*M / 2
main()
{
    int i, n = 0;
    for (i = 1; i <= NUM; i++);
    {
        n++;
        printf("%d", n);
    }
    printf("\n");
}

A) 5 B) 6 C) 8 D) 9

查看答案与解析

答案:C

解析: 本题考查宏定义的文本替换机制。

  1. 宏替换是纯文本替换,不带括号。
  2. NUM 展开过程:
    • NUM = (M + 1)*M / 2
    • 替换 M(N+1 + 1)*N+1 / 2
    • 替换 N(2+1 + 1)*2+1 / 2
  3. 计算展开后的表达式:
    • NUM = (4)*2 + 1/2
    • 根据优先级,先算乘除,后算加法:4 * 2 = 81 / 2 = 0
    • NUM = 8 + 0 = 8
  4. for (i = 1; i <= 8; i++); 循环从 i=1 执行到 i=8,共执行了 8 次。

故选 C


难度: ⭐⭐⭐ 考点: #宏替换 #运算符优先级

💡 学习锦囊

📖 相关公式与知识点:

  • 宏定义只是简单的文本替换,一定要注意运算符的结合优先级,必要时在宏定义中加括号。

思路分析

宏替换千万不能先计算宏的值,必须先原样展开表达式,再按优先级计算。

易错点

  • 先入为主地算出 $M = 3$,然后带入 $NUM = 4 * 3 / 2 = 6$
🔄 举一反三
  1. 若宏定义为 #define NUM ((M+1)*M/2),展开后的值是多少?
    查看练习答案与解析

    答案:6 解析:带括号后,表达式变为 ((2+1+1)*(2+1)/2),即 4 * 3 / 2 = 6

(16) 设有以下语句, 则 (D) 不是对 a 数组元素的正确引用, 其中 $0 \leq i < 10$

c
int a[10] = {0,1,2,3,4,5,6,7,8,9}, *p = a;

A) a[p - a] B) *(&a[i]) C) p[i] D) ((a + i))

查看答案与解析

答案:D

解析: 本题考查指针与数组元素的引用。

  1. A 选项:p - a 是指针相减,结果为 0。a[0] 是对首元素的正确引用。
  2. B 选项:&a[i] 取得第 i 个元素的地址,再解引用 *,等价于 a[i]。正确。
  3. C 选项:p 指向数组首地址,指针可以像数组名一样通过下标引用,p[i] 等价于 a[i]。正确。
  4. D 选项:a + i 是第 i 个元素的地址,*(a + i) 已经取出了该元素的值(整型)。再次对整型使用解引用运算符 *(*(a + i)) 是非法的。

故选 D


难度: ⭐⭐ 考点: #指针与数组 #解引用

💡 学习锦囊

📖 相关公式与知识点:

  • a[i] $\Leftrightarrow$ *(a + i)

思路分析

注意解引用的层数,对非指针类型使用解引用 * 是语法错误。

易错点

  • 混淆了指针地址的增加与解引用的关系。
🔄 举一反三
  1. 表达式 *(p + i) 是否是对 a[i] 的正确引用?
    查看练习答案与解析

    答案:是 解析p 指向首地址,p+i 即为 a[i] 的地址,解引用得到元素本身。

(17) 以下程序的输出结果是 (B)。

c
#include <stdio.h>
main()
{
    int i = 1, j = 3;
    printf("%d", i++);
    {
        int i = 0;
        i += j * 2;
        printf("%d,%d", i, j);
    }
    printf("%d,%d\n", i, j);
}

A) 1,6,3,1,3 B) 1,6,3,2,3 C) 1,6,3,6,3 D) 1,7,3,2,3

查看答案与解析

答案:B

解析: 本题考查局部变量的作用域与遮蔽。

  1. 外层定义 i = 1, j = 3
  2. printf("%d", i++); 打印外层 i 的当前值 1,随后外层 i 自增变为 2。
  3. 进入内层复合语句(花括号):
    • 重新定义了局部变量 int i = 0;,这会遮蔽外层的 i
    • i += j * 2:内层 i 变为 $0 + 3 \times 2 = 6$
    • printf 打印内层 ij(内层无 j,使用外层),输出 6,3
  4. 退出复合语句,内层 i 销毁,外层 i 重新可见。
  5. printf 打印外层 i(值为 2)和 j(值为 3),输出 2,3
  6. 合并输出为 16,32,3

故选 B


难度: ⭐⭐ 考点: #变量作用域 #作用域遮蔽

💡 学习锦囊

📖 相关公式与知识点:

  • 复合语句内部定义的变量生命周期仅限于该语句块。

思路分析

注意进入花括号后,新定义的同名变量会使外层的同名变量在当前块内不可见。

易错点

  • 混淆内外层 i 的值变化,以为外层 i 也变成了 6。
🔄 举一反三
  1. 若将内层 int i = 0; 改为 i = 0;,最终输出结果是什么?
    查看练习答案与解析

    答案:1,6,3,6,3 解析:没有新定义变量,修改的就是外层的 i

(18) 以下程序的输出结果是 (A)。

c
#include <stdio.h>
int func(int a, int b)
{
    static int m = 0, i = 2;
    i += m + 1;
    m = i + a + b;
    return m;
}
main()
{
    int k = 4, m = 1, p;
    p = func(k, m);
    printf("%d,", p);
    p = func(k, m);
    printf("%d\n", p);
}

A) 8,17 B) 8,16 C) 8,20 D) 8,8

查看答案与解析

答案:A

解析: 本题考查 static 静态局部变量。

  1. 第一次调用 func(4, 1)
    • 静态变量 m=0, i=2 初始化。
    • i += 0 + 1 $\Rightarrow$ i = 3
    • m = 3 + 4 + 1 = 8
    • 返回 8,打印 8,
  2. 第二次调用 func(4, 1)
    • 静态变量保留上次的值,即 m=8, i=3。不再执行初始化。
    • i += 8 + 1 $\Rightarrow$ i = 12
    • m = 12 + 4 + 1 = 17
    • 返回 17,打印 17

故输出为 8,17,选 A(原题答案 D 存在逻辑错误,修正为 A)。


难度: ⭐⭐⭐ 考点: #静态局部变量 #函数调用

💡 学习锦囊

📖 相关公式与知识点:

  • static 变量只在程序加载时初始化一次,并在多次调用间持久保存其值。

思路分析

每次调用函数时,静态变量都在上一次运算的终值基础上继续计算。

易错点

  • 每次调用都对 mi 重新赋初值。
🔄 举一反三
  1. 若去掉 static 关键字,输出结果是什么?
    查看练习答案与解析

    答案:8,8 解析:变为常规局部变量,每次调用都重新初始化。

(19) 设有以下语句:

c
char str1[] = "string", str2[8], *str3, *str4 = "string";

则 (D) 不是对库函数 strcpy 的正确调用。

A) strcpy(str1,"HELLO1"); B) strcpy(str2,"HELLO2"); C) strcpy(str3,"HELLO3"); D) strcpy(str4,"HELLO4");

查看答案与解析

答案:D

解析: 本题考查 strcpy 函数的使用以及内存权限。

  1. strcpy 的原型为 char *strcpy(char *dest, const char *src);,其功能是将源字符串复制到目标地址中。目标地址必须是可写的且有足够的空间
  2. D 选项:str4 指向一个字符串常量 "string"。字符串常量存放在只读数据段。尝试使用 strcpy 修改只读内存会引发“内存写入违规”崩溃。

注:C 选项中 str3 是野指针,写入也是未定义行为。但从考点来看,D 选项考查字符串常量不能修改的知识点更为明确。

故选 D


难度: ⭐⭐⭐ 考点: #strcpy函数 #字符串常量 #指针安全性

💡 学习锦囊

📖 相关公式与知识点:

  • 字符串常量位于代码区(只读),不能被修改。
  • 数组名是地址常量,其指向的内存是可写的。

思路分析

检查目的地址是否具有写权限。

易错点

  • 误认为指针只要指向了字符串就可以随意修改。
🔄 举一反三
  1. strcpy(str1, "A"); 是否正确?
    查看练习答案与解析

    答案:正确 解析str1 空间足够,且可以被覆写。

(20) C 语言中形参的缺省存储类别是 (A)。

A) 自动(auto) B) 静态(static) C) 寄存器(register) D) 外部(extern)

查看答案与解析

答案:A

解析: 本题考查 C 语言变量存储类别。

  1. 在 C 语言中,函数的形参在函数调用时分配内存,函数执行完毕后自动销毁。
  2. 因此,形参的默认存储类别是 auto(自动变量),通常存储在栈区。

故选 A


难度: ⭐ 考点: #存储类别 #形参

💡 学习锦囊

📖 相关公式与知识点:

  • auto:自动变量(默认)。
  • static:静态变量。
  • extern:外部声明。
  • register:寄存器变量。

思路分析

识记基础概念即可。

易错点

  • 混淆了局部变量、形参的生存期。
🔄 举一反三
  1. 全局变量的缺省存储类别是什么?
    查看练习答案与解析

    答案:extern(外部变量) 解析:全局变量默认具有外部链接属性。

二、填空题(本题共6空,每空5分,共30分)

(1) 以下程序求 a 数组中的所有素数的和,函数 isprime 用来判断自变量是否为素数。素数是只能被 1 和本身整除且大于 1 的自然数。

c
#include <stdio.h>
main()
{
    int i, a[10], *p = a, sum = 0;
    printf("Enter 10 num:\n");
    for (i = 0; i < 10; i++)
        scanf("%d", &a[i]);
    for (i = 0; i < 10; i++)
        if (isprime(*(p + ___①___)) == 1)
        {
            printf("%d", *(a + i));
            sum += *(a + i);
        }
    printf("\nThe sum=%d\n", sum);
}
int isprime(int x)
{
    int i;
    for (i = 2; i <= x / 2; i++)
        if (x % i == 0)
            return (0);
    return (1);
}
查看答案与解析

答案:① i

解析:p 指向数组 a 的首元素,*(p + i) 等价于 a[i],即访问数组第 i 个元素。循环遍历数组,对每个元素调用 isprime 判断是否为素数。


难度: ⭐⭐ 考点: #指针与数组 #素数判断

💡 学习锦囊

📖 相关公式与知识点:

  • *(p + i) 等价于 p[i] 等价于 a[i](当 p=a 时)。
  • 素数判断:从 2 到 x/2 检查是否有因子。

思路分析

指针 p 已指向数组首地址,通过 p+i 偏移访问各元素。

🔄 举一反三
  1. 若将 *(p + i) 改为 p[i],功能是否相同?
    查看练习答案与解析

    答案:相同 解析*(p+i)p[i] 在 C 语言中完全等价。

(2) 以下程序调用 invert 函数按逆序重新放置 a 数组中元素的值。a 数组中的值在 main 函数中读入。

c
#include <stdio.h>
#define N 10
void invert(int *s, int i, int j)
{
    int t;
    if (i < j)
    {
        t = *(s + i);
        *(s + i) = *(s + j);
        *(s + j) = t;
        invert(s, ___②___, j - 1);
    }
}
main()
{
    int a[N], i;
    for (i = 0; i < N; i++)
        scanf("%d", a + ___③___);
    invert(a, 0, N - 1);
    for (i = 0; i < N; i++)
        printf("%d", a[i]);
    printf("\n");
}
查看答案与解析

答案:② i + 1(或 ++i) ③ i

解析:invert 是递归函数,交换 s[i]s[j] 后,递归处理子数组 s[i+1 ... j-1],所以第二个参数应为 i+1。③ scanf 需要地址,a + i&a[i]


难度: ⭐⭐⭐ 考点: #递归 #数组逆序 #指针

💡 学习锦囊

📖 相关公式与知识点:

  • 递归三要素:终止条件(i≥j)、递归体(交换+递归调用)、参数变化(i+1, j-1)。
  • a + i 等价于 &a[i]

思路分析

递归逆序:每次交换首尾元素,然后对去掉首尾的子数组递归。

🔄 举一反三
  1. 用循环实现数组逆序,如何写?
    查看练习答案与解析

    答案

    c
    for (i = 0, j = N-1; i < j; i++, j--)
    { t = a[i]; a[i] = a[j]; a[j] = t; }

(3) 以下程序的功能是将字符串 a 中下标值为偶数的元素由小到大排序,其他元素不变。

c
#include <stdio.h>
main()
{
    char a[] = "labchmfye", t;
    int i, j;
    for (i = 0; i < 7; i += 2)
        for (j = i + 2; j < 9; ___④___)
            if (___⑤___)
            {
                t = a[i];
                a[i] = a[j];
                a[j] = t;
            }
    puts(a);
    printf("\n");
}
查看答案与解析

答案:④ j += 2a[i] > a[j]

解析: ④ 只对偶数下标排序,所以 j 的步长也是 2。⑤ 选择排序的比较条件:如果前面的元素大于后面的元素则交换,实现升序排列。


难度: ⭐⭐ 考点: #选择排序 #字符串

💡 学习锦囊

📖 相关公式与知识点:

  • 选择排序:每次找到最小元素放到前面。
  • 只对特定下标排序时,步长相应调整。

思路分析

偶数下标:0, 2, 4, 6, 8。i 从 0 开始步长 2,j 从 i+2 开始步长 2。

🔄 举一反三
  1. 若要对奇数下标元素排序,如何修改?
    查看练习答案与解析

    答案:i 从 1 开始,步长仍为 2。

三、阅读程序题(本题共4小题,每题5分,共20分)

(1) 阅读下列程序:

c
#include <stdio.h>
main()
{
    int i, j, row, column, m;
    static int array[3][3] = {{100, 200, 300}, {28, 72, -30}, {-850, 2, 6}};
    m = array[0][0];
    for (i = 0; i < 3; i++)
        for (j = 0; j < 3; j++)
            if (array[i][j] < m)
            {
                m = array[i][j];
                row = i;
                column = j;
            }
    printf("%d,%d,%d\n", m, row, column);
}

上述程序的输出结果是_____。

查看答案与解析

答案: -850,2,0

解析: 程序遍历 3×3 二维数组,寻找最小值。初始 m=100(array[0][0])。遍历过程中:28<100→m=28;-30<28→m=-30;-850<-30→m=-850。最终最小值 -850 位于 array[2][0],即 row=2, column=0。


难度: ⭐⭐ 考点: #二维数组 #求最值

💡 学习锦囊

📖 相关公式与知识点:

  • 求最小值:初始化 m 为第一个元素,遍历比较更新。
  • static 修饰的局部数组在数据段分配内存。

思路分析

逐元素比较,记录最小值和位置。

🔄 举一反三
  1. 若将 if (array[i][j] < m) 改为 if (array[i][j] > m),输出什么?
    查看练习答案与解析

    答案300,0,2解析:改为求最大值,最大值为 300,位于 array[0][2]。

(2) 下面程序的输出结果是_____。

c
#include <stdio.h>
main()
{
    int a = 3, b = 2, c = 1;
    c -= ++b;
    b *= a + c;
    {
        int b = 5, c = 12;
        c /= b * 2;
        a = c;
        printf("%d,%d,%d,", a, b, c);
        a += --c;
    }
    printf("%d,%d,%d\n", a, b, c);
}
查看答案与解析

答案: 1,5,1,2,3,-2

解析: 外层:++b 使 b=3,c -= 3 即 c=1-3=-2。a+c = 3+(-2)=1,b *= 1 即 b=3。进入内层块:定义局部 b=5, c=12。c /= b*2 即 c=12/10=1(整数除法)。a=c=1(修改外层 a)。打印 1,5,1,a += --c 即 a=1+0=1。退出内层,外层 b=3, c=-2。打印 1,3,-2。合并:1,5,1,2,3,-2


难度: ⭐⭐⭐ 考点: #作用域 #复合赋值 #整数除法

💡 学习锦囊

📖 相关公式与知识点:

  • 内层块中同名变量遮蔽外层变量。
  • 整数除法截断小数。

思路分析

分内外层分别追踪变量值,注意内层修改外层 a 的影响。

易错点

  • 混淆内外层 b、c 的值。
🔄 举一反三
  1. 若去掉内层的 int b=5, c=12; 声明,输出结果是什么?
    查看练习答案与解析

    答案0,3,0,0,3,-2解析:内层直接使用外层变量,c=(-2)/(3*2)=0(整数除法)。

(3) 请读程序:

c
#define PR(ar) printf("%d", ar)
main()
{
    int j, a[] = {1, 3, 5, 7, 9, 11, 13, 15}, *p = a + 5;
    for (j = 3; j; j--)
    {
        switch (j)
        {
        case 1:
        case 2:
            PR(*p++);
            break;
        case 3:
            PR(*(--p));
        }
    }
}

上面程序的输出结果是_____。

查看答案与解析

答案: 9911

解析: 初始 p=a+5 指向 a[5]=11。循环 j=3,2,1:

  • j=3:case 3,--p 使 p 指向 a[4]=9,PR(*(--p)) 输出 9。
  • j=2:case 2,PR(*p++) 输出当前 *p=9,然后 p++ 指向 a[5]=11。
  • j=1:case 1(无 break 穿透到 case 2),PR(*p++) 输出 11,p++ 指向 a[6]=13。

合并输出:9911。


难度: ⭐⭐⭐ 考点: #switch穿透 #指针运算 #宏定义

💡 学习锦囊

📖 相关公式与知识点:

  • switch 中若无 break,会穿透到下一个 case。
  • *p++:先取 *p,再 p++。
  • *(--p):先 --p,再取 *p。

思路分析

逐轮追踪 p 的位置变化和输出值。

易错点

  • 混淆 *p++(后缀++优先级高于*,但后缀效果是先用后增)和 (*p)++
🔄 举一反三
  1. 若将 *p++ 改为 (*p)++,输出结果是什么?
    查看练习答案与解析

    答案9,10,12(数组元素被修改) 解析(*p)++ 先取 *p 的值输出,然后对该元素自增。

(4) 下面程序的输出是_____。

c
long fun5(int n)
{
    long s;
    if ((n == 1) || (n == 2))
        s = 2;
    else
        s = n + fun5(n - 1);
    return s;
}
main()
{
    long x;
    x = fun5(4);
    printf("%ld\n", x);
}
查看答案与解析

答案: 9

解析: 递归展开:fun5(4) = 4 + fun5(3) = 4 + (3 + fun5(2)) = 4 + 3 + 2 = 9。


难度: ⭐⭐ 考点: #递归 #函数调用

💡 学习锦囊

📖 相关公式与知识点:

  • 递归公式:f(1)=f(2)=2,f(n)=n+f(n-1)(n>2)。
  • 展开:f(4)=4+f(3)=4+3+f(2)=4+3+2=9。

思路分析

从顶层逐层展开,直到终止条件 n=1 或 n=2。

🔄 举一反三
  1. fun5(5) 的值是多少?
    查看练习答案与解析

    答案:14 解析:5+4+3+2=14。

四、程序题(10分)

  1. 输入两个整数,求他们相除的余数,用带参数的宏来编程实现。
查看答案与解析

参考答案:

c
#include <stdio.h>
#define MOD(a, b) ((a) % (b))

main()
{
    int x, y;
    printf("请输入两个整数: ");
    scanf("%d %d", &x, &y);
    printf("%d %% %d = %d\n", x, y, MOD(x, y));
}

解析: 带参数的宏 MOD(a, b) 在预处理阶段展开为 ((a) % (b))。宏参数用括号包裹防止运算符优先级问题。%% 在 printf 中输出 % 字符。


难度: ⭐⭐ 考点: #带参数宏 #求余运算

💡 学习锦囊

📖 相关公式与知识点:

  • 带参数宏:#define 宏名(参数列表) 替换文本
  • 宏参数建议加括号:((a) % (b)) 而非 a % b

思路分析

宏在预处理阶段进行文本替换,不是函数调用,没有类型检查。

易错点

  • 宏参数不加括号,如 #define MOD(a,b) a%b,当调用 MOD(x+1, y) 时展开为 x+1%y,结果错误。
🔄 举一反三
  1. 用带参数宏实现求两个数的最大值。
    查看练习答案与解析

    答案#define MAX(a, b) ((a) > (b) ? (a) : (b))解析:三目运算符配合括号确保安全。

你正在阅读的是会员专属文档,💕 限时特惠进行中
你尚未登录,目前新用户可获3天体验会员,去登录